#pragma once
#include "Struct.h"

class DataFilter {
public:
	static DataFilter* get() {
		static auto instance = new DataFilter;
		return instance;
	}

	bool isInitialized() { return m_viewMatrix != Mat_Zero && m_projectionMatrix != Mat_Zero; }

	void slotCameraMatrix(const Mat& viewMatrix, const Mat& projectionMatrix);

	/** @return true: data is valid; false: data is invalid */
	bool checkValid(const ModelArg& modelArg);
	bool checkValid(LineArg& lineArg);

	bool isOutOfRenderArea(const P& pos);
	bool isOutOfRenderArea(const LineEq& eq);

	void recalculateEqStartEnd(LineEq& eq);

	inline const P& skyLeftP() { return m_3DRenderAreaMap[SkyLeft]; }
	inline const P& skyRightP() { return m_3DRenderAreaMap[SkyRight]; }
	inline const P& bottomLeftP() { return m_3DRenderAreaMap[BottomLeft]; }
	inline const P& bottomRightP() { return m_3DRenderAreaMap[BottomRight]; }

	inline float skylineZ() { return skyLeftP().z; }
	inline float bottomZ() { return bottomLeftP().z; }

	inline const std::function<float(float)>& get2DScalerFunc() { return s_2dScalerFunc; }
	
private:
	DataFilter() = default;

	enum CornerDir { SkyLeft, SkyRight, BottomLeft, BottomRight };

	P mapTo3DXZPlane(int screenX, int screenY);

	Mat m_viewMatrix = Mat_Zero, m_projectionMatrix = Mat_Zero;

	CMap<CornerDir, P> m_3DRenderAreaMap;

	std::function<float(float)> s_2dScalerFunc;
};